################################################################################
# fscheme (C) Copyright funnyos@qq.com 2018
#
# This software is freely distributable under the terms of the MIT 
# License. See the file LICENSE for details.
################################################################################
.data
zero:          .double   0.0
ten:           .double   10.0
one:           .double   1.0
minus_one:     .double   -1.0
FPositive:     .asciiz   "2/3"
FZero:         .asciiz   "0/1"
FNegtive:      .asciiz   "-4/3"
err_msg:       .asciiz   "Not a valid fraction string."
################################################################################
.text

.globl main

################################################################################
# main()
# entry point
################################################################################
main:
    la   $a0, FPositive
    jal  str_to_fraction
    move $a0, $v0
    move $a1, $v1
    jal  print_fraction
    
    la   $a0, FZero
    jal  str_to_fraction
    move $a0, $v0
    move $a1, $v1
    jal  print_fraction
    
    la   $a0, FNegtive
    jal  str_to_fraction
    move $a0, $v0
    move $a1, $v1
    jal  print_fraction
    
    li   $v0, 17  # exit
    syscall
################################################################################
# str_to_fraction()
# 
################################################################################
str_to_fraction:
    addi $sp, $sp, -20
    sw   $ra, 16($sp)
    sw   $t3, 12($sp)
    sw   $t2, 8($sp)
    sw   $t1, 4($sp)
    sw   $t0, 0($sp)
    
    move $v0, $zero
    move $v1, $zero
    move $t3, $zero
    
    lbu  $t0, 0($a0)
    li   $t1, '-'
    bne  $t0, $t1, str_to_fraction.positive
    li   $t2, 1
    addi $a0, $a0, 1
    j    str_to_fraction.calc
str_to_fraction.positive:
    move $t2, $zero
    li   $t1, '+'
    bne  $t0, $t1, str_to_fraction.calc
    addi $a0, $a0, 1
    
str_to_fraction.calc:
    
    lbu  $t0, 0($a0)
    beq  $t0, $zero, str_to_fraction.done
    li   $t1, '/'
    bne  $t0, $t1, str_to_fraction.not_slash
    li   $t3, 1
    addi $a0, $a0, 1
    j    str_to_fraction.calc
str_to_fraction.not_slash:
    li   $t1, '0'
    bltu $t0, $t1, str_to_fraction.error
    li   $t1, '9'
    bltu $t1, $t0, str_to_fraction.error
    subi $t0, $t0, '0'
    beq  $t3, $zero, str_to_fraction.other
    mul  $v1, $v1, 10
    add  $v1, $v1, $t0
    j    str_to_fraction.inc
str_to_fraction.other:
    mul  $v0, $v0, 10
    add  $v0, $v0, $t0
str_to_fraction.inc:
    addi $a0, $a0, 1
    j    str_to_fraction.calc
str_to_fraction.done:
    beq  $t3, $zero, str_to_fraction.error
    beq  $t2, $zero, str_to_fraction.exit
    mul  $v0, $v0, -1
    j    str_to_fraction.exit
str_to_fraction.error:
    la   $a0, err_msg
    li   $v0, 4
    syscall
    li   $v0, 17  # exit
    syscall
    
str_to_fraction.exit:
    lw   $t0, 0($sp)
    lw   $t1, 4($sp)
    lw   $t2, 8($sp)
    lw   $t3, 12($sp)
    lw   $ra, 16($sp)
    addi $sp, $sp, 20
    jr $ra


################################################################################
# print_fraction()
# 
################################################################################
print_fraction:
    addi $sp, $sp, -4
    sw   $ra, 0($sp)
    
    li   $v0, 1
    syscall
    
    li   $a0, '/'
    li   $v0, 11
    syscall
    
    move $a0, $a1
    li   $v0, 1
    syscall
    
    lw   $ra, 0($sp)
    addi $sp, $sp, 4
    jr $ra

